package com.bdd.bean;

import com.bdd.utils.Constant;
import com.bdd.utils.Tools;

import java.util.*;
import java.util.List;

/**
 * Created by msi on 2016/5/3 0003.
 */
public class ResultLine {
    BusStop srcStop;
    BusStop minStop;
    BusStop maxStop;
    BusLine busLine;

    public BusStop getSrcStop() {
        return srcStop;
    }

    public void setSrcStop(BusStop srcStop) {
        this.srcStop = srcStop;
    }

    public BusStop getMinStop() {
        return minStop;
    }

    public void setMinStop(BusStop minStop) {
        this.minStop = minStop;
    }

    public BusStop getMaxStop() {
        return maxStop;
    }

    public void setMaxStop(BusStop maxStop) {
        this.maxStop = maxStop;
    }

    public BusLine getBusLine() {
        return busLine;
    }

    public void setBusLine(BusLine busLine) {
        this.busLine = busLine;
    }

    public List<Points> getPointsList() {
        return pointsList;
    }

    public void setPointsList(List<Points> pointsList) {
        this.pointsList = pointsList;
    }

    public Map<Integer, Double> getGrade() {
        return grade;
    }

    public void setGrade(Map<Integer, Double> grade) {
        this.grade = grade;
    }

    List<Points> pointsList = new ArrayList<>();
    Map<Integer, Double> grade = new HashMap<Integer, Double>();

    public ResultLine(BusStop srcStop, BusStop minStop, BusStop maxStop, BusLine busLine) {
        this.srcStop = srcStop;
        this.minStop = minStop;
        this.maxStop = maxStop;
        this.busLine = busLine;
        setPointsListAndGrade();
    }

    private void setPointsListAndGrade() {
        int src = getNeareast(srcStop, busLine);
        int min = getNeareast(minStop, busLine);
        int max = getNeareast(maxStop, busLine);
        //分情况分析src在中间，则要分成两段来计算
        grade = new HashMap<Integer, Double>();
        if (src > min && src < max) {
            grade = new HashMap<Integer, Double>();
            pointsList = new ArrayList<>();
            pointsList.addAll(getPolylineWithinDistace(min, src, busLine));
            grade.putAll(getGrade(min, src, busLine));
            pointsList.addAll(getPolylineWithinDistace(src, max, busLine));
            grade.putAll(getGrade(src, max, busLine));
        }
        if (src > max && src < min) {
            pointsList = new ArrayList<>();
            grade = new HashMap<Integer, Double>();
            pointsList.addAll(getPolylineWithinDistace(max, src, busLine));
            grade.putAll(getGrade(max, src, busLine));
            pointsList.addAll(getPolylineWithinDistace(src, min, busLine));
            grade.putAll(getGrade(src, min, busLine));
        }
        //src在两侧
        if (src >= min && src >= max) {
            pointsList = new ArrayList<>();
            grade = new HashMap<Integer, Double>();
            int min_Index = Math.min(min, max);
            pointsList.addAll(getPolylineWithinDistace(min_Index, src, busLine));
            grade.putAll(getGrade(min_Index, src, busLine));
        }
        if (src <= min && src <= max) {
            pointsList = new ArrayList<>();
            grade = new HashMap<Integer, Double>();
            int max_Index = Math.max(min, max);
            pointsList.addAll(getPolylineWithinDistace(src, max_Index, busLine));
            grade.putAll(getGrade(src, max_Index, busLine));
        }
    }


    private Map<Integer, Double> getGrade(int start, int end, BusLine busLine) {
        Map<Integer, Double> tempGrade = new HashMap<Integer, Double>();
        List<Points> allpolines = busLine.getPolyline();
        Points startPoints = allpolines.get(start);
        double[] startPoints_Prj = Tools.lonLat2Mercator(startPoints.getX(), startPoints.getY());
        Points endPoints = allpolines.get(end);
        double[] endPoints_Prj = Tools.lonLat2Mercator(endPoints.getX(), endPoints.getY());
        double dist = Math.sqrt(Math.pow((startPoints_Prj[0] - endPoints_Prj[0]), 2) + Math.pow((startPoints_Prj[1] - endPoints_Prj[1]), 2));
        double k = (startPoints_Prj[1] - endPoints_Prj[1]) / (startPoints_Prj[0] - endPoints_Prj[0]);
        if (k > 0 && (startPoints_Prj[0] - endPoints_Prj[0]) > 0) {//第一象限
            tempGrade.put(Constant._1, dist);
        } else if (k >= 0 && (startPoints_Prj[0] - endPoints_Prj[0]) < 0) {//第三象限
            tempGrade.put(Constant._3, dist);
        } else if (k < 0 && (startPoints_Prj[0] - endPoints_Prj[0]) >= 0) {//第四象限
            tempGrade.put(Constant._4, dist);
        } else {//第二象限
            tempGrade.put(Constant._2, dist);
        }
        return tempGrade;
    }

    private List<Points> getPolylineWithinDistace(int start, int end, BusLine busLine) {
        double tempDistance = 0;
        List<Points> polines = new ArrayList<>();
        List<Points> allpolines = busLine.getPolyline();
        int breakIndex = -1;
        for (int i = start; i < end; i++) {
            Points startPoints = allpolines.get(i);
            double[] startPoints_Prj = Tools.lonLat2Mercator(startPoints.getX(), startPoints.getY());
            Points tempPoints = allpolines.get(i + 1);
            double[] tempPoints_Prj = Tools.lonLat2Mercator(tempPoints.getX(), tempPoints.getY());
            tempDistance = tempDistance + Math.sqrt(Math.pow((startPoints_Prj[0] - tempPoints_Prj[0]), 2) + Math.pow((startPoints_Prj[1] - tempPoints_Prj[1]), 2));
            if (tempDistance < Constant.DISTANCE_BUS) {
                polines.add(startPoints);
            } else {
                breakIndex = i;
                break;
            }
        }
        if (breakIndex != -1) {//如果超出了5km break
            polines.add(allpolines.get(breakIndex));
        } else {//如果没有就补充最后一个
            polines.add(allpolines.get(end));
        }
        return polines;
    }

    //查找距离线中最近的点的序号
    private int getNeareast(BusStop busStop, BusLine busLine) {
        double temp = Double.MAX_VALUE;
        int index = -1;
        double[] busStop_Prj = Tools.lonLat2Mercator(busStop.getPoints().getX(), busStop.getPoints().getY());
        int i = 0;
        for (Points tempPoints : busLine.getPolyline()) {
            double[] tempPoints_Prj = Tools.lonLat2Mercator(tempPoints.getX(), tempPoints.getY());
            double dist = Math.sqrt(Math.pow((busStop_Prj[0] - tempPoints_Prj[0]), 2) + Math.pow((busStop_Prj[1] - tempPoints_Prj[1]), 2));
            if (temp > dist) {
                temp = dist;
                index = i;
            }
            i++;
        }
        return index;
    }
}